﻿#include "forward_control.h"
#include <QDebug>


forward_Control::forward_Control(qintptr client,QObject *parent) : QThread(parent)
{
    this->m_ClientDescriptor = client;
}

forward_Control::~forward_Control()
{
    if(m_ClientSocket != nullptr)
    {
        m_ClientSocket->disconnectFromHost();
        m_ClientSocket->close();
        m_ClientSocket->deleteLater();
    }
}

void forward_Control::run()
{
    m_ClientSocket = new QTcpSocket();
    if(!m_ClientSocket->setSocketDescriptor(this->m_ClientDescriptor))
    {
        qDebug()<<"绑定socket失败";
        return;
    }
    m_ClientAddress = m_ClientSocket->peerAddress().toString();
    m_ClientSocket->setProtocolTag(VERSION);
    connect(m_ClientSocket,&QTcpSocket::readyRead,this,&forward_Control::processRequest,Qt::DirectConnection);
    connect(m_ClientSocket,&QTcpSocket::disconnected,this,&forward_Control::processDisconnected,Qt::DirectConnection);
    
    this->exec();
}

void forward_Control::processRequest()
{
    qDebug()<<"处理节点请求";
    if(m_ClientSocket == nullptr)  
    {
        this->exit();
        return;
    }
    QByteArray buff = m_ClientSocket->readAll(); //读取数据
    qDebug()<<"解析数据: "<<buff;
    
    //数据是json的，解析成为json
    QJsonParseError parseError;
    QJsonDocument document = QJsonDocument::fromJson(buff,&parseError);
    if(parseError.error != QJsonParseError::NoError)
    {
        qDebug()<<"报文出错";
        exit();
        return;
    }
    
    //解析报文为json
    QJsonObject dataObject = document.object();  
    
    QString command = dataObject["control"].toString();  //获取指令
    qDebug()<<"command: "<<command;
    if(command == NEWPORT)  
    {
        //开放新端口
        commandNewPort(dataObject);
    }else if(command ==CLOSEPORT)
    {
        //断开端口
        commandClosePort(dataObject);
    }
    
}

void forward_Control::processDisconnected()
{
    qDebug()<<"断开连接 "<<m_ClientAddress;
    //断开连接释放所有监的server
    foreach(int port , m_VectorPort)
    {
        Forward_System::freedPort(port);
    }
    this->exit();
}

void forward_Control::commandNewPort(QJsonObject& dataObject)
{
    QJsonObject info = dataObject["info"].toObject();
    int port = info["forwardPort"].toString().toInt();
    QString errmsg = "";
    if(port <=1024 || port> 65535)
    {
        qDebug()<<"端口范围不正确: "<<port;
        errmsg = ERRORDATA;  //检验是否在正确范围内
        return;
    }
    
    if(Forward_System::portIsOccupy(port))
    {
        qDebug()<<"端口在占用: "<<port;
        errmsg = ISOCCUPY;//如果在占用
        return;
    }
    
    if(!errmsg.isEmpty())
    {
        dataObject.insert("errmsg",errmsg);
        qDebug()<<"出错: "<<errmsg;
        m_ClientSocket->write(QJsonDocument(dataObject).toJson());
        return;
    }
    
    //通知控制中心开启端口
    Forward_Offer *offer = new Forward_Offer(m_ClientSocket->peerAddress(),info);
    //当被代理方的服务端口数量不够时，
    connect(offer,&Forward_Offer::addService,this,&forward_Control::commandAddService,Qt::DirectConnection);
    //判断是否监听成功
    if(offer->listen(QHostAddress::AnyIPv4,port))
    {
        dataObject.insert("message",PORTOPEN.data());
        qDebug()<<"添加记录，以便客户离开时删除 ";
        
        //添加全局记录
        Forward_System::userPort(port,offer);
        //局部记录，用于断开时释放
        m_VectorPort.append(port);
        
    }else{
        qDebug()<<"端口被占用";
        dataObject.insert("errmsg",ISOCCUPY.data());
    }
    qDebug()<<QJsonDocument(dataObject).toJson();
    QByteArray sdbuff = QJsonDocument(dataObject).toJson();
    m_ClientSocket->write(sdbuff);
}

void forward_Control::commandClosePort(QJsonObject &dataObject)
{
    qDebug()<<"关闭一个转发的端口";
    QJsonObject info = QJsonDocument::fromJson(dataObject["info"].toString().toUtf8()).object();
    int port = info["forwardPort"].toString().toInt();
    
    int pIndex = m_VectorPort.indexOf(port);
    
    if(pIndex != -1){ //判断是不是这个用户的端口，以免结束了他人的端口
        Forward_System::freedPort(port);
        m_VectorPort.remove(pIndex);
    }
    dataObject.insert("message",CLOSEPORT.data());
    //不管有没有这个端口我们都返回一个端口已关闭的信息
    m_ClientSocket->write(QJsonDocument(dataObject).toJson());
}

void forward_Control::commandAddService(QJsonObject info)
{
    qDebug()<<"通知连接服务端口: "<<info["forwardPort"].toString();
    QJsonObject obj;
    obj.insert("command",ADDSERVICE.data());
    obj.insert("errmsg","");
    obj.insert("info",QJsonDocument(info).toJson().data());
    m_ClientSocket->write(QJsonDocument(obj).toJson());
}
